




XMPPError(Condition * condition) {
	init(condition);
}


XMPPError(Condition * condition, std::string & messageText) :
	message(messageText)
{
	init(condition);
}


XMPPError(int code) : code(code) {}


XMPPError(int code, std::string & message) : code(code), message(message) {}


XMPPError(int code, Type & type, std::string & condition, std::string & message,
            std::list<PacketExtension*> & extension) :
	code(code),
	type(type),
	condition(condition),
	message(message),
	applicationExtensions(extension) 
{}


void init(Condition * c) {
	// Look for the condition and its default code and type
	ErrorSpecification * defaultErrorSpecification = ErrorSpecification::specFor(condition);
	this->condition = c->getValue();
	if (defaultErrorSpecification != NULL) {
		// If there is a default error specification for the received condition,
		// it get configured with the infered type and code.
		type = defaultErrorSpecification->getType();
		code = defaultErrorSpecification->getCode();
	}
}


std::string toXML() {
	std::string buf;
	buf.append("<error code=\"").append(code).append("\"");
	if (type != UNDEFINED) {
		buf.append(" type=\"");
		buf.append(type);
		buf.append("\"");
	}
	buf.append(">");
	if (condition != NULL) {
		buf.append("<").append(condition->getValue());
		buf.append(" xmlns=\"urn:ietf:params:xml:ns:xmpp-stanzas\"/>");
	}
	if (!message.empty()) {
		buf.append("<text xml:lang=\"en\" xmlns=\"urn:ietf:params:xml:ns:xmpp-stanzas\">");
		buf.append(message);
		buf.append("</text>");
	}
	for (std::list<PacketExtension*>::iterator it = applicationExtensions.begin();
			it != applicationExtensions.end(); it ++) {
		buf.append((*it)->toXML());
	}
	buf.append("</error>");
	return buf;
}

std::string toString() {
	std::string txt ;
	if (condition != NULL) {
		txt.append(condition->getValue());
	}
	txt.append("(").append(code).append(")");
	if (!message.empty()) {
		txt.append(" ").append(message);
	}
	return txt;
}


std::list<PacketExtension*> getExtensions() {
	return applicationExtensions;
}


PacketExtension * getExtension(std::string & elementName, std::string & nameSpace) {
	if (!applicationExtensions.empty() && !elementName.empty() && !nameSpace.empty() ) {
		for (std::list<PacketExtension*>::iterator it = applicationExtensions.begin();
				it != applicationExtensions.end(); it ++) {
			if (elementName == (*it)->getElementName() && nameSpace == (*it)->getNamespace()) {
				return *it;
			}
		}
	}
	return NULL;
}


void addExtension(PacketExtension * extension) {
	applicationExtensions.add(extension);
}


void setExtension(std::list<PacketExtension*> & extension) {
	applicationExtensions = extension;
}


XMPPError::Condition * Condition::interna_server_error = new Condition("internal-server-error");
XMPPError::Condition * Condition::forbidden = new Condition("forbidden");
XMPPError::Condition * Condition::bad_request = new Condition("bad-request");
XMPPError::Condition * Condition::conflict = new Condition("conflict");
XMPPError::Condition * Condition::feature_not_implemented = new Condition("feature-not-implemented");
XMPPError::Condition * Condition::gone = new Condition("gone");
XMPPError::Condition * Condition::item_not_found = new Condition("item-not-found");
XMPPError::Condition * Condition::jid_malformed = new Condition("jid-malformed");
XMPPError::Condition * Condition::no_acceptable = new Condition("not-acceptable");
XMPPError::Condition * Condition::not_allowed = new Condition("not-allowed");
XMPPError::Condition * Condition::not_authorized = new Condition("not-authorized");
XMPPError::Condition * Condition::payment_required = new Condition("payment-required");
XMPPError::Condition * Condition::recipient_unavailable = new Condition("recipient-unavailable");
XMPPError::Condition * Condition::redirect = new Condition("redirect");
XMPPError::Condition * Condition::registration_required = new Condition("registration-required");
XMPPError::Condition * Condition::remote_server_error = new Condition("remote-server-error");
XMPPError::Condition * Condition::remote_server_not_found = new Condition("remote-server-not-found");
XMPPError::Condition * Condition::remote_server_timeout = new Condition("remote-server-timeout");
XMPPError::Condition * Condition::resource_constraint = new Condition("resource-constraint");
XMPPError::Condition * Condition::service_unavailable = new Condition("service-unavailable");
XMPPError::Condition * Condition::subscription_required = new Condition("subscription-required");
XMPPError::Condition * Condition::undefined_condition = new Condition("undefined-condition");
XMPPError::Condition * Condition::unexpected_condition = new Condition("unexpected-condition");
XMPPError::Condition * Condition::request_timeout = new Condition("request-timeout");


XMPPError::ErrorSpecification * XMPPError::ErrorSpecification::specFor(Condition * condition) {
	if(instances.empty()) { 
		errorSpecifications(); 
	}
	return instances[condition];
}


void XMPPError::ErrorSpecification::errorSpecifications() {
	instances.insert(std::map<Condition*, ErrorSpecification*> :: value_type(Condition:: interna_server_error, new ErrorSpecification(
				Condition::interna_server_error, WAIT, 500)));
	instances.insert(std::map<Condition*, ErrorSpecification*> :: value_type(Condition:: forbidden, new ErrorSpecification(Condition::forbidden,
				AUTH, 403)));
	instances.insert(std::map<Condition*, ErrorSpecification*> :: value_type(Condition:: bad_request, new XMPPError.ErrorSpecification(
				Condition::bad_request, MODIFY, 400)));
	instances.insert(std::map<Condition*, ErrorSpecification*> :: value_type(Condition:: item_not_found, new XMPPError.ErrorSpecification(
				Condition::item_not_found, CANCEL, 404)));
	instances.insert(std::map<Condition*, ErrorSpecification*> :: value_type(Condition:: conflict, new XMPPError.ErrorSpecification(
				Condition::conflict, CANCEL, 409)));
	instances.insert(std::map<Condition*, ErrorSpecification*> :: value_type(Condition:: feature_not_implemented, new XMPPError.ErrorSpecification(
				Condition::feature_not_implemented, CANCEL, 501)));
	instances.insert(std::map<Condition*, ErrorSpecification*> :: value_type(Condition:: gone, new XMPPError.ErrorSpecification(
				Condition::gone, MODIFY, 302)));
	instances.insert(std::map<Condition*, ErrorSpecification*> :: value_type(Condition:: jid_malformed, new XMPPError.ErrorSpecification(
				Condition::jid_malformed, MODIFY, 400)));
	instances.insert(std::map<Condition*, ErrorSpecification*> :: value_type(Condition:: no_acceptable, new XMPPError.ErrorSpecification(
				Condition::no_acceptable, MODIFY, 406)));
	instances.insert(std::map<Condition*, ErrorSpecification*> :: value_type(Condition:: not_allowed, new XMPPError.ErrorSpecification(
				Condition::not_allowed, CANCEL, 405)));
	instances.insert(std::map<Condition*, ErrorSpecification*> :: value_type(Condition:: not_authorized, new XMPPError.ErrorSpecification(
				Condition::not_authorized, AUTH, 401)));
	instances.insert(std::map<Condition*, ErrorSpecification*> :: value_type(Condition:: payment_required, new XMPPError.ErrorSpecification(
				Condition::payment_required, AUTH, 402)));
	instances.insert(std::map<Condition*, ErrorSpecification*> :: value_type(Condition:: recipient_unavailable, new XMPPError.ErrorSpecification(
				Condition::recipient_unavailable, WAIT, 404)));
	instances.insert(std::map<Condition*, ErrorSpecification*> :: value_type(Condition:: redirect, new XMPPError.ErrorSpecification(
				Condition::redirect, MODIFY, 302)));
	instances.insert(std::map<Condition*, ErrorSpecification*> :: value_type(Condition:: registration_required, new XMPPError.ErrorSpecification(
				Condition::registration_required, AUTH, 407)));
	instances.insert(std::map<Condition*, ErrorSpecification*> :: value_type(Condition:: remote_server_not_found, new XMPPError.ErrorSpecification(
				Condition::remote_server_not_found, CANCEL, 404)));
	instances.insert(std::map<Condition*, ErrorSpecification*> :: value_type(Condition:: remote_server_timeout, new XMPPError.ErrorSpecification(
				Condition::remote_server_timeout, WAIT, 504)));
	instances.insert(std::map<Condition*, ErrorSpecification*> :: value_type(Condition:: remote_server_error, new XMPPError.ErrorSpecification(
				Condition::remote_server_error, CANCEL, 502)));
	instances.insert(std::map<Condition*, ErrorSpecification*> :: value_type(Condition:: resource_constraint, new XMPPError.ErrorSpecification(
				Condition::resource_constraint, WAIT, 500)));
	instances.insert(std::map<Condition*, ErrorSpecification*> :: value_type(Condition:: service_unavailable, new XMPPError.ErrorSpecification(
				Condition::service_unavailable, CANCEL, 503)));
	instances.insert(std::map<Condition*, ErrorSpecification*> :: value_type(Condition:: subscription_required, new XMPPError.ErrorSpecification(
				Condition::subscription_required, AUTH, 407)));
	instances.insert(std::map<Condition*, ErrorSpecification*> :: value_type(Condition:: undefined_condition, new XMPPError.ErrorSpecification(
				Condition::undefined_condition, WAIT, 500)));
	instances.insert(std::map<Condition*, ErrorSpecification*> :: value_type(Condition:: unexpected_condition, new XMPPError.ErrorSpecification(
				Condition::unexpected_condition, WAIT, 400)));
	instances.insert(std::map<Condition*, ErrorSpecification*> :: value_type(Condition:: request_timeout, new XMPPError.ErrorSpecification(
				Condition::request_timeout, CANCEL, 408)));

}
